package org.dftproject.genesis.core.http;

import java.io.File;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Environment;
import com.sleepycat.je.EnvironmentConfig;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.util.UtfOps;

public class LocalHttpCache {

	private static final Log log = LogFactory.getLog(LocalHttpCache.class);

	private Environment environment;

	public LocalHttpCache(String path) {
		File cacheFile = new File(path);
		cacheFile.mkdirs();

		try {
			EnvironmentConfig environmentConfig = new EnvironmentConfig();
			environmentConfig.setAllowCreate(true);
			environment = new Environment(cacheFile, environmentConfig);
		} catch (DatabaseException e) {
			log.error("Failed to open HTTP cache environment", e);
		}
	}

	public void close() {
		if (environment != null) {
			try {
				environment.close();
				environment = null;
			} catch (DatabaseException e) {
				log.error("Failed to close HTTP cache environment", e);
			}
		}
	}

	public String getResponse(String url) {
		Database cache = null;

		try {
			cache = getCache();
			if (cache != null)
				return getResponse(cache, url);
		} finally {
			try {
				if (cache != null)
					cache.close();
			} catch (DatabaseException e) {
			}
		}

		return null;
	}

	public void putResponse(String url, String response) {
		Database cache = null;

		try {
			cache = getCache();
			if (cache != null)
				putResponse(cache, url, response);
		} finally {
			try {
				if (cache != null)
					cache.close();
			} catch (DatabaseException e) {
			}
		}
	}

	protected Database getCache() {
		try {
			DatabaseConfig cacheConfig = new DatabaseConfig();
			cacheConfig.setAllowCreate(true);
			return environment.openDatabase(null, "cache", cacheConfig);
		} catch (DatabaseException e) {
			log.error("Failed to open cache database", e);
		}

		return null;
	}

	protected String getResponse(Database cache, String url) {
		try {
			DatabaseEntry key = new DatabaseEntry(UtfOps.stringToBytes(url));
			DatabaseEntry data = new DatabaseEntry();

			if (cache.get(null, key, data, LockMode.DEFAULT) == OperationStatus.SUCCESS) {
				byte[] bytes = data.getData();
				return UtfOps.bytesToString(bytes, 0, bytes.length);
			}
		} catch (DatabaseException e) {
			log.error("Failed to get response from cache for " + url, e);
		}

		return null;
	}

	protected void putResponse(Database cache, String url, String response) {
		try {
			DatabaseEntry key = new DatabaseEntry(UtfOps.stringToBytes(url));
			DatabaseEntry data = new DatabaseEntry(UtfOps.stringToBytes(response));
			cache.put(null, key, data);
		} catch (DatabaseException e) {
			log.error("Failed to put response in cache for " + url, e);
		}
	}

}
